package com.fabriciojf.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFileChooser;

/**
 * Classe para manipulacao de arquivos
 *
 * @author fabricio
 * @since 18/03/2010
 * @version 1.1 18/05/2010
 */
public class FileCS {

    /**
     * Singleton
     */
    private static FileCS instance = new FileCS();
    public static FileCS getInstance() {
        return instance;
    }

    /**
     * Retorna o endereço do arquivo composto por dir + nome + extensão
     *
     * @return
     */
    public File getPath() {
        JFileChooser fc = new JFileChooser();
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        int resultado = fc.showOpenDialog(null);

        if (resultado == JFileChooser.CANCEL_OPTION) {
            return null;
        }
        return fc.getSelectedFile();
    }

    /**
     * Retorna o path do arquivo no formato string = dir + nome + extensão
     *
     * @return
     */
    public String getPathToString() {
        File arquivo = getPath();
        if (arquivo == null) {
            return "";
        }
        return arquivo.toString();
    }

    /**
     * Retorna somente o diretorio do arquivo
     *
     * @param arquivo
     * @return
     */
    public String getDir(String arquivo) {
        String dir = arquivo.substring(0, arquivo.lastIndexOf(File.separator));
        return dir;
    }

    /**
     * Retorna o nome do arquivo sem extensão
     *
     * @param arquivo
     * @return
     */
    public String getFileNameNoExt(String arquivo) {
        String nomeArquivo;
        if (arquivo.lastIndexOf('.') > 0) {
            nomeArquivo = arquivo.substring(arquivo.lastIndexOf(File.separator), arquivo.lastIndexOf('.'));
        } else {
            nomeArquivo = arquivo.substring(arquivo.lastIndexOf(File.separator), arquivo.length());
        }
        return nomeArquivo;
    }

    /**
     * Retorna o nome do arquivo com extensão
     *
     * @param arquivo
     * @return
     */
    public String getFileName(String arquivo) {
        return arquivo.substring(arquivo.lastIndexOf(File.separator), arquivo.length());
    }

    /**
     * Retorna a extensão do arquivo
     *
     * @param arquivo
     * @return
     */
    public String getExt(String arquivo) {
        if (arquivo.lastIndexOf('.') > 0) {
            return arquivo.substring(arquivo.lastIndexOf('.'), arquivo.length());
        }
        return "";
    }

    /**
     * Copia um arquivo da origem para um destino especifico
     *
     * @param origem
     * @param destino
     */
    public boolean copy(File origem, File destino) {
        try {
            if (!origem.exists()) {
                throw new Exception("Arquivo de Origem inexistente");             
            }

            FileInputStream fisOrigem = new FileInputStream(origem);
            FileOutputStream fisDestino = new FileOutputStream(destino);
            FileChannel fcOrigem = fisOrigem.getChannel();
            FileChannel fcDestino = fisDestino.getChannel();
            fcOrigem.transferTo(0, fcOrigem.size(), fcDestino);
            fisOrigem.close();
            fisDestino.close();
            
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * Copia todo o conteudo do diretorio "dirOrigem"
     * para o diretorio "dirDestino"
     * @param origem
     * @param destino
     */
    public void copyDir(File dirOrigem, File dirDestino) {

        if (dirOrigem.isDirectory()) {
            if (!dirDestino.exists()) {
                dirDestino.mkdir();
            }

            String[] children = dirOrigem.list();
            for (int i = 0; i < children.length; i++) {
                copyDir(new File(dirOrigem, children[i]), new File(dirDestino, children[i]));
            }
        } else {
            copy(dirOrigem, dirDestino);
        }
    }

    /**
     * Deleta um arquivo recursivamente
     *
     * @param dir
     * @return
     */
    public boolean deleteDir(File dir) {

        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }

        // Agora o diretório está vazio, restando apenas deletá-lo.
        return dir.delete();
    }

    /**
     * Cria um diretório completo
     *
     * @param diretorio
     * @return
     */
    public boolean createDir(String diretorio) {

        try {
            File novoDiretorio = new File(diretorio);
            novoDiretorio.mkdirs();
            return true;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            return false;
        }

    }

    /**
     * Apaga um diretório e o cria novamente
     *
     * @param diretorio
     */
    public void reCreateDir(String diretorio) {
        deleteDir(new File(diretorio));
        createDir(diretorio);
    }

    /**
     * Este método retorna os arquivos de um diretório cujo nome contenham uma
     * palavra especificada como parâmetro.
     */
    public List<String> listFileForFilter(File dir, String word) {

        List<String> files = new ArrayList<String>();
        for (File f : dir.listFiles()) {
            if (f.getName().indexOf(word) >= 0) {
                files.add(f.getName());
                System.out.println(f.getName());
            }

        }
        return files;
    }

    /**
     * Lista todos os arquivos do diretorio "dir"
     */
    public List<File> listAllFiles(File dir) {

        List<File> files = new ArrayList<File>();
        listarRecursivamente(files, dir);

        return files;
    }

    /**
     * Busca recursiva por arquivos e determinado diretorio
     * @param arquivos
     * @param diretorio
     */
    private void listarRecursivamente(List<File> arquivos, File diretorio) {
        if (diretorio.isDirectory() || diretorio.isFile()) {
            for (File f : diretorio.listFiles()) {
                if (f.isDirectory()) {
                    listarRecursivamente(arquivos, f);
                } else {
                    arquivos.add(f);
                }
            }
        }
    }
}
